#!/usr/bin/env python
#encoding : utf-8

from utils import RequestDict
try:
	from urlparse import parse_qs
except ImportError:
	from cgi import parse_qs
from cStringIO import StringIO


class Request(object):
	def __init__(self, environ, setting):
		self.environ = environ
		self.setting = setting
		self.session_enabled = False
		self.method = environ['REQUEST_METHOD']

		self.content_type, opts = parse_header_option(environ.get('CONTENT_TYPE', 'text/html'))
		self._charset = opts.get('charset')
		if not self._charset:
			self._charset = getattr(setting, 'request_charset', None)

	def DICT_INPUT(self):	
		self.dict_input = RequestDict(parse_qs(self.raw_post_data, True))
		return self.dict_input

	@property
	def raw_post_data(self):
		try:
			return self._raw_post_data
		except AttributeError:
			try:
				content_length = int(self.environ.get('CONTENT_LENGTH', 0))
			except ValueError:
				content_length = 0

			if hasattr(self.setting, 'max_input_length') and\
					self.setting.max_input_length < content_length:
				raise ValueError, 'Maximum content length exceeded'

			buf = StringIO()
			size, buf_len = content_length, 1<<16 # 16k
			stream = self.environ['wsgi.input']
			while size > 0:
				# The application should not attempt to read more data than
				# is specified by the CONTENT_LENGTH variable.
				input = stream.read( min(size, buf_len) )
				if not input:
					break
				buf.write(input)
				size -= buf_len

			self._raw_post_data = buf.getvalue()
			buf.close()

			return self._raw_post_data


	def __getitem__(self, key):
		key = key.upper().replace('-', '_')
		return self.environ.get(key) or self.environ.get('HTTP_' + key, None)

	@property
	def charset(self):
		return self._charset

	def get_request_uri(self):
		env = self.environ
		uri = env.get('REQUEST_URI')
		if not uri:
			uri = env['SCRIPT_NAME']
			if 'PATH_INFO' in env:
				uri = uri + env['PATH_INFO']
			if env['QUERY_STRING']:
				uri = uri + '?' + env['QUERY_STRING']
		return uri

	def get_query_string(self):
		return self.environ['QUERY_STRING']

def parse_header_option(header):
	def _tokenize(string):
		while string[:1] == ';':
			string = string[1:]
			end = string.find(';')
			while end > 0 and string.count('"', 0, end) % 2:
				end = string.find(';', end + 1)
			if end < 0:
				end = len(string)
			value = string[:end]
			yield value.strip()
			string = string[end:]

	parts = _tokenize(';' + header)
	name = parts.next()
	extra = {}
	for part in parts:
		if '=' in part:
			key, value = part.split('=', 1)
			extra[key.strip().lower()] = value.strip()
		else:
			extra[part.strip()] = None
	return name, extra 

if __name__ == '__main__':
	pass
